interface EventBus {
	on(event: string, callback: (...args: any[]) => void): void;

	once(event: string, callback: (...args: any[]) => void): void;

	emit(event: string, ...args: any[]): boolean;

	off(event?: string, callback?: (...args: any[]) => void): void;
}

class SimpleEventBus implements EventBus {
	private events: Map<string, Set<Function>>;

	constructor() {
		this.events = new Map();
	}

	on(event: string, callback: (...args: any[]) => void): void {
		let callbacks = this.events.get(event);
		if (!callbacks) {
			callbacks = new Set();
			this.events.set(event, callbacks);
		}
		callbacks.add(callback);
	}

	once(event: string, callback: (...args: any[]) => void): void {
		const onceCallback = (...args: any[]): void => {
			this.off(event, onceCallback);
			callback(...args);
		};
		this.on(event, onceCallback);
	}

	emit(event: string, ...args: any[]): boolean {
		const callbacks = this.events.get(event);
		if (callbacks) {
			for (const callback of callbacks) {
				callback(...args);
			}
			return true;
		}
		return false;
	}

	off(event?: string, callback?: (...args: any[]) => void): void {
		if (event) {
			const callbacks = this.events.get(event);
			if (callbacks) {
				if (callback) {
					callbacks.delete(callback);
				} else {
					this.events.delete(event);
				}
			}
		} else {
			this.events.clear();
		}
	}
}

export default new SimpleEventBus();
